#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>  

#include "pub_lib.h"
#include "cli.h"

static int set_fonts_style(int argc, char **argv,void *ptCmd);
static int set_fonts_size(int argc, char **argv,void *ptCmd);
static int get_fonts_detail(int argc, char **argv,void *ptCmd);

static int set_color_background(int argc, char **argv,void *ptCmd);
static int set_color_font(int argc, char **argv,void *ptCmd);
static int get_color(int argc, char **argv,void *ptCmd);

static int set_dlog_lvl(int argc, char **argv,void *ptCmd);
static int get_dlog_lvl(int argc, char **argv,void *ptCmd);
static int set_dlog_fmt(int argc, char **argv,void *ptCmd);
static int get_dlog_fmt(int argc, char **argv,void *ptCmd);

T_Command CmdSet_Def[] = 
{
    {
        "set fonts style",
        set_fonts_style,
        0,
        0,
        1,
        "example:set fonts style STSONG"
    },
    {
        "set fonts size",
        set_fonts_size,
        8,
        64,
        1,
        "example:set fonts size (8~64)"
    },
    {
        "get fonts detail",
        get_fonts_detail,
        0,
        0,
        0,
        "example:get fonts detail"
    },
    {
        "set color background",
        set_color_background,
        0,
        0xffffff,
        1,
        "example:set color background (0~0xffffff)"
    },
    {
        "set color font",
        set_color_font,
        0,
        0xffffff,
        1,
        "example:set color font (0~0xffffff)"
    },
    {
        "get color",
        get_color,
        0,
        0,
        0,
        "example:get color"
    },
    {
        "set dlog lvl",
        set_dlog_lvl,
        0,
        5,
        1,
        "example:set dlog lvl (0~5)"
    },
    {
        "get dlog lvl",
        get_dlog_lvl,
        0,
        0,
        0,
        "example:get dlog lvl"
    },
    {
        "set dlog fmt",
        set_dlog_fmt,
        0,
        0xff,
        2,
        "example:set dlog fmt [lvl](0~5) [fmt](0~0xff)"
    },
    {
        "get dlog fmt",
        get_dlog_fmt,
        0,
        5,
        1,
        "example:get dlog fmt [level](0~5)"
    },
    {
        NULL,
        NULL,
        0,
        0,
        0,
        NULL
    }
};

/**
 * @brief 检验字符串是否合法
 * 
 * @param str 字符串指针
 * @return int 合法：1;非法：0
 */
static int check_is_valid_string(const char *str) {
    // 检查每个字符
    while (*str) {
        // 如果不是字母或数字，则返回 0
        if (!isalnum((unsigned char)*str)) {
            return 0;
        }
        str++;
    }
    // 所有字符合法
    return 1;
}

/**
 * @brief 检验输入的uint32_t参数是否合法
 * 
 * @param value 输入的uint32_t参数
 * @return int 合法：1;非法：0
 */
static int check_is_valid_int(uint32_t value,void *ptCmd)
{
    PT_Command temp = (PT_Command)ptCmd;
    if((value > temp->iMaxmum)||(value < temp->iMinimum))
    {
        return 0;
    }
    else
    {
        return 1;
    }      
}

/**
 * @brief uint型转uint8
 * 
 * @param src uint32型
 * @param dest uint8
 * @return int 成功 1;失败 0;
 */
static int uint32_to_uint8(uint32_t src,uint8_t *dest)
{
    if (src < 0 || src > 255) {
        return 0;
    } else {
        *dest = (uint8_t)src;
    }
    return 1;
}

/**
 * @brief uint32型转uint8
 * 
 * @param src int型
 * @param dest uint8
 * @return int 成功 1;失败 0;
 */
static int uint32_to_uint16(uint32_t src,uint16_t *dest)
{
    if (src > UINT16_MAX) {
        return 0;
    } else {
        *dest = (uint16_t)src;
    }
    return 1;
}

/**
 * @brief 设置fonts风格
 */
static int set_fonts_style(int argc, char **argv,void *ptCmd)
{
    int iRet;
    char cFontsFile[16] = {0};

    if(strlen(argv[0]) > sizeof(cFontsFile))
    {
        fprintf(stderr,"cFontsFile %s is too long!\r\n", cFontsFile);
        return -1;
    }

    if (!check_is_valid_string(argv[0]))
    {
        fprintf(stderr,"cFontsFile %s is invalid!\r\n", argv[0]);
        return -2;
    }
    sprintf(cFontsFile,"%s.TTF",argv[0]);
    //strcpy(cFontsFile,argv[0]);
    cFontsFile[15] = '\0';


    iRet = PubSetFontsDetail(cFontsFile, 0);
    if (!iRet)
    {
        fprintf(stderr,"set cFontsFile %s successful!\r\n", cFontsFile);
        return 0;
    }
    else
    {
        fprintf(stderr,"error code:%d\r\n", iRet);
        return -3;
    }
}

/**
 * @brief 设置字体大小
 */
static int set_fonts_size(int argc, char **argv,void *ptCmd)
{
    int iRet;
    uint32_t FontSize = 0;

    sscanf(argv[0],"%d",&FontSize);

    if (!check_is_valid_int(FontSize, ptCmd))
    {
        fprintf(stderr,"FontSize %d is invalid!\r\n", FontSize);
        return -1;
    }
    iRet = PubSetFontsDetail("default", FontSize);
    if (!iRet)
    {
        return 0;
    }
    else
    {
        fprintf(stderr,"error code:%d\r\n", iRet);
        return -2;
    }
}

/**
 * @brief 获取字体信息
 */
static int get_fonts_detail(int argc, char **argv,void *ptCmd)
{
    int iRet;
    uint32_t FontSize = 0;
    char cFontsFile[16] = {0};

    iRet = PubGetFontsDetail(cFontsFile, &FontSize);
    if (!iRet)
    {
        fprintf(stderr,"FontsFile:%s FontSize:%d\r\n",cFontsFile,FontSize);
        return 0;
    }
    else
    {
        fprintf(stderr,"error code:%d\r\n", iRet);
        return -2;
    }
    
}

/**
 * @brief 设置背景颜色
 */
static int set_color_background(int argc, char **argv,void *ptCmd)
{
    int iRet;
    uint32_t color = 0;

    sscanf(argv[0],"%x",&color);
    
    if (!check_is_valid_int(color, ptCmd))
    {
        fprintf(stderr,"color %x is invalid!\r\n", color);
        return -1;
    }
    iRet = PubSetColor(0, color);
    if (!iRet)
    {
        fprintf(stderr,"set background color %x successful!\r\n", color);
        return 0;
    }
    else
    {
        fprintf(stderr,"error code:%d\r\n", iRet);
        return -2;
    }
}

/**
 * @brief 设置字体颜色
 */
static int set_color_font(int argc, char **argv,void *ptCmd)
{
    int iRet;
    uint32_t color = 0;

    sscanf(argv[0],"%x",&color);

    if (!check_is_valid_int(color, ptCmd))
    {
        fprintf(stderr,"color %x is invalid!\r\n", color);
        return -1;
    }
    iRet = PubSetColor(1, color);
    if (!iRet)
    {
        fprintf(stderr,"set font color %x successful!\r\n", color);
        return 0;
    }
    else
    {
        fprintf(stderr,"error code:%d\r\n", iRet);
        return -2;
    }
}

/**
 * @brief 获取背景和字体颜色
 */
static int get_color(int argc, char **argv,void *ptCmd)
{
    int iRet;
    int i;
    uint32_t color = 0;

    for (i = 0; i < 2; i++)
    {
        iRet = PubGetColor(i, &color);
        if (!iRet)
        {
            fprintf(stderr,"%s %d\r\n",i?"background color:":"font color:",color);
        }
        else
        {
            fprintf(stderr,"error code:%d\r\n", iRet);
            return -2;
        }
    }
    return 0;
}

/**
 * @brief 设置dlog等级
 */
static int set_dlog_lvl(int argc, char **argv,void *ptCmd)
{
    int iRet;
    int tmp = 0;
    uint8_t lvl;

    sscanf(argv[0],"%u",&tmp);


    if (!check_is_valid_int(tmp,ptCmd))
    {
        fprintf(stderr,"tmp %d is invalid!\r\n", tmp);
        return -1;
    }
    if (!uint32_to_uint8(tmp,&lvl))
    {
        fprintf(stderr,"level %d is invalid!\r\n", (int)lvl);
        return -1;
    }
    iRet = PubSetDlogLvl((uint8_t)lvl);
    if (!iRet)
    {
        fprintf(stderr,"set dlog lvl %d successful!\r\n", (int)lvl);
        return 0;
    }
    else
    {
        fprintf(stderr,"error code:%d\r\n", iRet);
        return -2;
    }
}

/**
 * @brief 获取dlog等级
 */
static int get_dlog_lvl(int argc, char **argv,void *ptCmd)
{
    int iRet;
    uint8_t lvl = 0;

    iRet = PubGetDlogLvl(&lvl);

    if (!iRet)
    {
        fprintf(stderr,"dlog lvl : %d\r\n",(int)lvl);
        return 0;
    }
    else
    {
        fprintf(stderr,"error code:%d\r\n", iRet);
        return -2;
    }
}

/**
 * @brief 设置dlog输出格式
 */
static int set_dlog_fmt(int argc, char **argv,void *ptCmd)
{
    int iRet;
    uint8_t lvl = 0;
    uint16_t fmt = 0;
    uint32_t tmp;


    sscanf(argv[0],"%u",&tmp);
    if (!uint32_to_uint8(tmp,&lvl))
    {
        fprintf(stderr,"level %d is invalid!\r\n", (int)lvl);
        return -1;
    }

    sscanf(argv[1],"%x",&tmp);
    if (!uint32_to_uint16(tmp,&fmt))
    {
        fprintf(stderr,"fmt %x is invalid!\r\n", (uint32_t)fmt);
        return -1;
    }

    iRet = PubSetDlogFmt(lvl,fmt);

    if (!iRet)
    {
        fprintf(stderr,"set dlog lvl : %d fmt: %x successful\r\n",(int)lvl,(uint32_t)fmt);
        return 0;
    }
    else
    {
        fprintf(stderr,"error code:%d\r\n", iRet);
        return -2;
    }
}

/**
 * @brief 获取dlog输出格式
 */
static int get_dlog_fmt(int argc, char **argv,void *ptCmd)
{
    int iRet;
    uint8_t lvl = 0;
    uint16_t fmt = 0;
    uint32_t tmp;


    sscanf(argv[0],"%u",&tmp);
    if (!check_is_valid_int(tmp,ptCmd))
    {
        fprintf(stderr,"tmp %d is invalid!\r\n", tmp);
        return -1;
    }
    if (!uint32_to_uint8(tmp,&lvl))
    {
        fprintf(stderr,"level %d is invalid!\r\n", (int)lvl);
        return -1;
    }

    iRet = PubGetDlogFmt(lvl,&fmt);

    if (!iRet)
    {
        fprintf(stderr,"get dlog lvl : %d fmt:%x\r\n",(int)lvl,(uint32_t)fmt);
        return 0;
    }
    else
    {
        fprintf(stderr,"error code:%d\r\n", iRet);
        return -2;
    }
}